package com.balisong.y.test;

import com.alibaba.fastjson.JSON;
import com.balisong.y.pojo.User;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpHost;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.unit.Fuzziness;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.aggregations.support.AggregatorSupplier;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;


import java.io.IOException;

//@SpringBootTest
public class testEsDemo2 {
    private RestHighLevelClient client;

    @BeforeEach
    public void init() {
        client = new RestHighLevelClient(RestClient.builder(new HttpHost("192.168.200.150", 9200, "http")));
        System.out.println(client);
    }

    @Test
    public void add() {
        System.out.println(client);
    }

    /**
     * 抽取查询数据后后台打印结果代码为查询结果方法:QueryResult
     *
     * @return
     * @Querybuilders 为工具类
     * @params
     */
    public void queryResult(SearchSourceBuilder builder) throws IOException {
        SearchRequest request = new SearchRequest("user");
        request.source(builder);
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //总条数
        System.out.println(response.getHits().getTotalHits().value);
        //遍历打印对象
        for (SearchHit hit : response.getHits().getHits()) {
            String userJsonStr = hit.getSourceAsString();
            System.out.println(JSON.parseObject(userJsonStr, User.class));
        }
    }

    /**
     * @return 测试查询所有
     * @params
     */
    @Test
    public void testQueryAll() throws IOException {
        SearchSourceBuilder builder = new SearchSourceBuilder();
        MatchAllQueryBuilder matchAllQuery = QueryBuilders.matchAllQuery();
        builder.query(matchAllQuery);
        SearchRequest request = new SearchRequest("user");
        request.source(builder);
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //总条数
        SearchHits hits = response.getHits();
        System.out.println("总记录数" + hits.getTotalHits().value);
        //遍历获取每个user
        for (SearchHit hit : hits.getHits()) {
            String userJsonStr = hit.getSourceAsString();
            //json解析为对象
            User user = JSON.parseObject(userJsonStr, User.class);
            System.out.println(user);
        }
    }

    /**
     * @return 词条查询
     * @params
     * @Term查询,词条不分词
     */
    @Test
    public void testTermQuery() throws IOException {
        SearchSourceBuilder builder = new SearchSourceBuilder();
        TermQueryBuilder termQuery = QueryBuilders.termQuery("note", "小红");
        builder.query(termQuery);
        SearchRequest request = new SearchRequest("user");
        request.source(builder);
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //查询数据总条数
        System.out.println("总条数" + response.getHits().getTotalHits().value);
        SearchHit[] hits = response.getHits().getHits();
        for (SearchHit hit : hits) {
            String userJosnStr = hit.getSourceAsString();
            User user = JSON.parseObject(userJosnStr, User.class);
            System.out.println(user);
        }
    }

    /**
     * @return
     * @params
     * @match查询, 即搜索的词条分词
     * 匹配分词查询,分词词条,查询所有包含分词词条的选项
     */
    @Test
    public void testMatchQuery() throws IOException {
        SearchSourceBuilder builder = new SearchSourceBuilder();
        MatchQueryBuilder matchQuery = QueryBuilders.matchQuery("note", "小红同学");
       /* MatchQueryBuilder matchQuery1 = QueryBuilders.matchQuery("name", "小红同学");
        matchQuery1.analyzer("ik_max_word");//指定分词器
        matchQuery1.operator(Operator.OR);*///指定查询结果类型
        builder.query(matchQuery);
        SearchRequest request = new SearchRequest("user");
        request.source(builder);
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        System.out.println(response.getHits().getTotalHits().value);
        for (SearchHit hit : response.getHits().getHits()) {
            String userJsonStr = hit.getSourceAsString();
            User user = JSON.parseObject(userJsonStr, User.class);
            System.out.println(user);
        }
    }

    /**
     * @return
     * @params
     * @模糊查询 修正错误查询
     */
    @Test
    public void testFuzzyQuery() throws IOException {
        SearchSourceBuilder builder = new SearchSourceBuilder();
        FuzzyQueryBuilder queryBuilder = QueryBuilders.fuzzyQuery("note", "小洪");
        queryBuilder.fuzziness(Fuzziness.ONE);
        queryBuilder.prefixLength(1);
        builder.query(queryBuilder);
        SearchRequest request = new SearchRequest("user");
        request.source(builder);
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //总条数
        System.out.println(response.getHits().getTotalHits().value);
        for (SearchHit hit : response.getHits().getHits()) {
            String userJsonStr = hit.getSourceAsString();
            User user = JSON.parseObject(userJsonStr, User.class);
            System.out.println(user);
        }
    }

    /**
     * @return
     * @params
     * @范围和排序查询
     */


    @Test
    public void testRangeAndSort() throws IOException {
        SearchSourceBuilder builder = new SearchSourceBuilder();
        RangeQueryBuilder queryBuilder = QueryBuilders.rangeQuery("age");
        queryBuilder.gte(20).lte(27);
        builder.query(queryBuilder);
        builder.sort("age", SortOrder.ASC).sort("id", SortOrder.ASC);
        SearchRequest request = new SearchRequest("user");
        request.source(builder);
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //总条数
        System.out.println(response.getHits().getTotalHits().value);
        for (SearchHit hit : response.getHits().getHits()) {
            String userJsonStr = hit.getSourceAsString();
            User user = JSON.parseObject(userJsonStr, User.class);
            System.out.println(user);
        }
    }

    /**
     * @return
     * @params
     * @queryStirng 多条件查询
     * @使用默认搜索域
     */
    @Test
    public void testQueryStr() throws IOException {
        SearchSourceBuilder builder = new SearchSourceBuilder();
        QueryStringQueryBuilder queryBuilder = QueryBuilders.queryStringQuery("黑马同学").defaultField("note");
        builder.query(queryBuilder);
        builder.sort("id", SortOrder.ASC);
        SearchRequest request = new SearchRequest("user");
        request.source(builder);

        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //总条数
        System.out.println(response.getHits().getTotalHits().value);
        for (SearchHit hit : response.getHits().getHits()) {
            String userJsonStr = hit.getSourceAsString();
            User user = JSON.parseObject(userJsonStr, User.class);
            System.out.println(user);
        }
    }

    /**
     * @return
     * @params
     * @多条件查询
     * @链式调用指定特定多域联合查询 指定关联式AND 或者 OR
     */
    @Test
    public void testQueryStrr() throws IOException {
        SearchSourceBuilder builder = new SearchSourceBuilder();
        QueryStringQueryBuilder queryBuilder = QueryBuilders.queryStringQuery("小红黑马同学").field("note").field("note").defaultOperator(Operator.OR);
        builder.query(queryBuilder);
        SearchRequest request = new SearchRequest("user");
        request.source(builder);
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //总条数
        System.out.println(response.getHits().getTotalHits().value);
        for (SearchHit hit : response.getHits().getHits()) {
            String userJsonStr = hit.getSourceAsString();
            User user = JSON.parseObject(userJsonStr, User.class);
            System.out.println(user);
        }
    }

    /**
     * @return
     * @bool查询 联合多条件查询
     * @should 指定满足条件关系为or
     * @must指定条件必须都满足
     * @must_no 指定条件都不符合的项
     * @params
     */
    @Test
    public void testBoolQuery() throws IOException {
        SearchSourceBuilder builder = new SearchSourceBuilder();

        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

        boolQueryBuilder.should(QueryBuilders.matchQuery("note", "同学"));
        boolQueryBuilder.filter(QueryBuilders.matchQuery("note", "黑马"));
        boolQueryBuilder.filter(QueryBuilders.rangeQuery("age").gte(20).lte(27));
        builder.query(boolQueryBuilder);
        queryResult(builder);
    }

    /**
     * 测试分页插叙
     * 与sort排序查询类似,都是对查询结果进行处理
     *
     * @return
     * @params
     */
    @Test
    public void testQueryByPage() throws IOException {
        SearchSourceBuilder builder = new SearchSourceBuilder();
        MatchAllQueryBuilder matchAllQuery = QueryBuilders.matchAllQuery();
        builder.query(matchAllQuery);
        builder.from(0).size(5);
        queryResult(builder);

    }

    /**
     * 测试查询结果高亮显示
     *
     * @return
     * @params
     */
    @Test
    public void testHighLights() throws IOException {
        SearchSourceBuilder builder = new SearchSourceBuilder();
        MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("note", "同学").analyzer("ik_max_word").operator(Operator.OR);
        builder.query(matchQueryBuilder);
        /*  builder.highlighter().field("note").preTags("<font style='color:red'>").postTags("</font>");*/
        builder.highlighter(new HighlightBuilder().field("note").preTags("<font style='color:red'>").postTags("</font>"));
        builder.sort("id", SortOrder.ASC);
        SearchRequest request = new SearchRequest("user");
        request.source(builder);
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //总条数
        System.out.println(response.getHits().getTotalHits().value);
        //遍历打印对象
        for (SearchHit hit : response.getHits().getHits()) {
            String userJsonStr = hit.getSourceAsString();
            User user = JSON.parseObject(userJsonStr, User.class);
            HighlightField highlightField = hit.getHighlightFields().get("note");
            Text[] fieldFragments = highlightField.getFragments();
            String highNote = StringUtils.join(fieldFragments);
            if (StringUtils.isNotBlank(highNote)) {
                user.setNote(highNote);
            }
            System.out.println(user);
        }
    }

    /**
     * 测试聚合查询
     *
     * @return
     * @params
     */
    @Test
    public void testAggs() throws IOException {
        SearchSourceBuilder builder = new SearchSourceBuilder();
        TermsAggregationBuilder aggregationBuilder = AggregationBuilders.terms("popular_colors");
        aggregationBuilder.field("color.keyword");
        builder.aggregation(aggregationBuilder);
        builder.size(0);
        SearchRequest request = new SearchRequest("car");
        request.source(builder);
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //总条数
        System.out.println(response.getHits().getTotalHits().value);

        Aggregations aggregations = response.getAggregations();
        Aggregation popular_colors = aggregations.getAsMap().get("popular_colors");
        Terms terms = (Terms) popular_colors;
        for (Terms.Bucket bucket : terms.getBuckets()) {
            System.out.println(bucket.getKeyAsString() + bucket.getDocCount());
        }

    }
}
